package com.boarsoft.rpc.sidecar;

import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.boarsoft.common.util.StringUtil;
import com.boarsoft.rpc.bean.RpcMethodConfig;
import com.boarsoft.rpc.bean.RpcReferenceConfig;
import com.boarsoft.rpc.bean.RpcRegistry;
import com.boarsoft.rpc.bean.RpcServiceConfig;
import com.boarsoft.rpc.core.RpcContext;

public class RpcSidecarBooker {
	private static final Logger log = LoggerFactory.getLogger(RpcSidecarBooker.class);

	@Autowired
	protected RpcContext rpcContext;

	protected String target;

	@PostConstruct
	public void init() throws Exception {
		RpcRegistry mr = rpcContext.getMyRegistry();
		Map<String, RpcReferenceConfig> rcMap = mr.getReferenceMap();
		Map<String, RpcServiceConfig> scMap = mr.getServiceMap();
		// 遍历已注册的服务引用，为真实的Reference创建Service
		for (Entry<String, RpcReferenceConfig> en : rcMap.entrySet()) {
			String id = en.getKey();
			RpcReferenceConfig rc = en.getValue();
			// 判重：serviceMap的key是sign
			if (scMap.containsKey(rc.getSign())) {
				continue;
			}
			RpcServiceConfig sc = new RpcServiceConfig(rc.getGroup(), rc.getName(), //
					rc.getInterfaceName(), rc.getVersion(), id);
			// 暂时约定：id不为空表示不需要匹配为服务提供者
			sc.setId(id.concat("Sidecar"));
			log.info("Regist sidecar service {}", sc);
			rpcContext.registService(sc, mr);
			// 为代理Service下每个方法创建SidecarInvoker，通过它来反射调用真实的Reference
			Map<String, RpcMethodConfig> mcMap = sc.getMethodConfigMap();
			for (RpcMethodConfig mc : mcMap.values()) {
				Integer mid = mc.getRelativeId();
				if (rpcContext.getDynamicInvoker(mid) == null) {
					log.info("Create sidecar reference method {} = {}", mid, mc);
					rpcContext.putDynamicInvoker(mid, new RpcSidecarInvoker(id, rpcContext));
				}
			}
		}
		// 遍历已注册的服务，为真实的Service创建Reference，但不创建DynamicInvoker
		for (Entry<String, RpcServiceConfig> en : scMap.entrySet()) {
			RpcServiceConfig sc = en.getValue();
			String id = sc.getRef();
			// 暂时约定：id不为空时是sidecar，referenceMap的key是id
			if (StringUtil.isNotEmpty(sc.getId()) || rpcContext.containsBean(id)) {
				continue;
			}
			RpcReferenceConfig rc = new RpcReferenceConfig(sc.getGroup(), sc.getName(), //
					sc.getInterfaceName(), sc.getVersion(), id);
			rc.setDirect(target);
			log.info("Regist sidecar reference {} = {}, target = {}", id, rc, target);
			rpcContext.registReference(rc, mr);
		}
	}

	public String getTarget() {
		return target;
	}

	public void setTarget(String target) {
		this.target = target;
	}

}
